package dao

import (
	"context"
	"encoding/json"
	"github.com/ecodeclub/ekit/slice"
	"github.com/olivere/elastic/v7"
	"strconv"
	"strings"
)

type ArticleElasticDAO struct {
	client *elastic.Client
	LikeElasticDAO
}
type Article struct {
	Id      int64    `json:"id"`
	Title   string   `json:"title"`
	Content string   `json:"content"`
	Status  int32    `json:"status"`
	Tags    []string `json:"tags"`
}

func NewArticleElasticDAO(client *elastic.Client) *ArticleElasticDAO {
	return &ArticleElasticDAO{client: client}
}

func (h *ArticleElasticDAO) InputArticle(ctx context.Context, article Article) error {
	_, err := h.client.Index().Index(ArticleIndexName).Id(strconv.FormatInt(article.Id, 10)).
		BodyJson(article).Do(ctx)
	return err
}
func (h *ArticleElasticDAO) Search(ctx context.Context, req ArticleReq, keywords []string) ([]Article, error) {
	queryString := strings.Join(keywords, " ")

	// 精确查找，已发表状态
	status := elastic.NewTermQuery("status", 2)

	//收藏的文章放前面
	collected := elastic.NewMatchQuery("id", slice.Map(req.collectArtids, func(idx int, src int64) any {
		return src
	})).Boost(4) //查询顺序：collect>tag=like>title==content

	tag := elastic.NewMatchQuery("id", slice.Map(req.tagArtids, func(idx int, src int64) any {
		return src
	})).Boost(2)

	liked := elastic.NewMatchQuery("id", slice.Map(req.likeArtids, func(idx int, src int64) any {
		return src
	})).Boost(2)
	// 内容或标题 模糊查找
	title := elastic.NewMatchQuery("title", queryString)
	content := elastic.NewMatchQuery("content", queryString)

	or := elastic.NewBoolQuery().Should(title, content, tag, liked, collected)
	and := elastic.NewBoolQuery().Must(status, or)

	sort := elastic.NewFieldSort("id").Desc()          //降序
	scoreSort := elastic.NewFieldSort("_score").Desc() //降序

	resp, err := h.client.Search(ArticleIndexName).SortBy(scoreSort, sort).Query(and).Do(ctx)
	if err != nil {
		return nil, err
	}
	res := make([]Article, 0, resp.Hits.TotalHits.Value)
	for _, hit := range resp.Hits.Hits {
		var t Article
		err = json.Unmarshal(hit.Source, &t)
		if err != nil {
			return nil, err
		}
		res = append(res, t)
	}
	return res, nil
}
